#pragma once
/*
 *	Copyright Â© 2008 University of Houston
 *	All rights reserved.
 */
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <vector>
#include "util.h"

using namespace std;

// #define FILTER_LETTERS "tscmrd" // Letters to indicate the filters

class resultsFilter
{
public:
	resultsFilter(float p=0.0f);
	virtual ~resultsFilter() {};

	/*
	 * Performs whatever analysis is necessary on the provided anaResultsList.
	 * @param 	resultsList		The analyzerResultList for filtering.
	 * @return analyzerResultList
	 * Returns a new analyzerResultList, which contains the filtered
	 * representation of [resultsList].
	 */
	virtual analyzerResultList doFilter(analyzerResultList resultsList);

	/*
	 * Defined here so that classes that inherit from resultsComparator
	 * can still be called as a resultsFilter object.
	 *
	 * Performs the results-comparison operation, and returns a set of
	 * lines to be added to the graph.
	 * @param 	longConns	Pointer to a vector containing the 'long'
	 *						chain results.
	 * @param 	shortConns	Pointer to a vector containing the 'short'
	 *						chain results.
	 * @return vector<resultList>
	 * Returns a vector of resultsList objects.  Each object represents
	 * a line, and will contain at least one point.
	 * If the operation fails, the size() of the returned vector will be Zero.
	 */
	virtual
	vector<analyzerResultList> doFilter(vector<analyzerResultList>* longConns,
										vector<analyzerResultList>* shortConns);

	/*
	 * Returns a pointer to a new object of the correct type.  This allocated
	 * memory must be manually deallocated.
	 * @param 	c		The character representation of the filter that is
	 * 					wanted.  For example, 's' for the Sort filter.
	 * @return 	resultsFilter*	
	 * Pointer to a new object of the proper type.
	 */
	static resultsFilter *getFilter(char c, float p=0.0f);
	
	// The parameter that is used by the resultsFilter object.
	float parameter;
};

class sortInOrder: public virtual resultsFilter
{
public:
	sortInOrder(float p=0.0f): resultsFilter(p) {};
	analyzerResultList doFilter(analyzerResultList resultsList);
};

class reverseSort: public virtual resultsFilter
{
public:
	reverseSort(float p=0.0f): resultsFilter(p) {};
	analyzerResultList doFilter(analyzerResultList resultsList);
};

class smoothResults : public virtual resultsFilter
{
public:
	smoothResults(float p=0.0f): resultsFilter(p) {};
	analyzerResultList doFilter(analyzerResultList resultsList);
};

class chompResults : public virtual resultsFilter
{
public:
	chompResults(float p=0.0f): resultsFilter(p) {};
	analyzerResultList doFilter(analyzerResultList resultsList);
};

class getMedian : public virtual resultsFilter
{
public:
	getMedian(float p=0.0f): resultsFilter(p) {};
	analyzerResultList doFilter(analyzerResultList resultsList);
};

class getRepVal : public virtual resultsFilter
{
public:
	getRepVal(float p=0.0f): resultsFilter(p) {};
	analyzerResultList doFilter(analyzerResultList resultsList);
};

class modeResults : public virtual resultsFilter
{
public:
	modeResults(float p=0.0f): resultsFilter(p) {};
	analyzerResultList doFilter(analyzerResultList resultsList);
	
private:
	void roundTo(int powerOfTen, analyzerResultList *p);
	long double findMode(analyzerResultList *p);
};

class crissCross : public virtual resultsFilter
{
public:
	crissCross(float p=0.0f): resultsFilter(p) {};
	vector<analyzerResultList> doFilter(vector<analyzerResultList>* longConns,
										vector<analyzerResultList>* shortConns);
};


//--------------Results Filter Pair/Parser------------------//

class resFilterPair
{
public:
	resFilterPair(char f, float p)
	{
		filterName = f;
		filterParameter = p;
	}

	~resFilterPair() {};

	static vector<resFilterPair> parseResFilters (string s);

	char			filterName;
	float			filterParameter;
};

